#include "my_string.h"

namespace sympsel {

std::ostream& operator<<(std::ostream& out, const string& s) {
    out << s._str;
    return out;
}

std::istream& operator>>(std::istream& in, string& s) {
    s.clear();
    
    char c;
    // 跳过前导空白字符
    while (in.get(c) && isspace(c)) {
    }
    
    // 如果已经到达文件末尾或出错，直接返回
    if (in.eof() || in.fail()) {
        in.setstate(std::ios::failbit);
        return in;
    }
    
    // 将第一个非空白字符放回输入流
    in.putback(c);
    
    // 动态读取非空白字符
    string temp;
    while (in.get(c) && !isspace(c)) {
        temp.push_back(c);
        if (in.fail()) {
            break;
        }
    }
    
    s = temp;
    return in;
}

void string::clear() {
    delete[] _str;
    _str = new char[1];
    _str[0] = '\0';
    _size = 0;
    _capacity = 0;
}

void string::swap(string& s) {
    string temp(*this);
    *this = s;
    s = temp;
}

size_t string::find(char c, size_t pos) const {
    for (size_t i = pos; i < _size; ++i) {
        if (_str[i] == c) {
            return i;
        }
    }
    return npos;
}

size_t string::find(char c, size_t pos, size_t n) const {
    for (size_t i = pos; i < std::min(pos + n, _size); ++i) {
        if (_str[i] == c) {
            return i;
        }
    }
    return npos;
}

int string::str_cmp(const string& s) const {
    for (size_t i = 0; i < _size; ++i) {
        if (_str[i] != s._str[i]) {
            return _str[i] - s._str[i];
        }
    }
    return 0;
}

int string::str_cmp(const string& s, size_t begin, size_t n) const {
    for (size_t i = 0; i < n; ++i) {
        int temp = begin + i;
        if (_str[begin + i] != s[i]) {
            return _str[begin + i] - s[i];
        }
    }
    return 0;
}

size_t string::find(const char* s, size_t pos) const {
    size_t len = strlen(s);
    if (len + pos > _size) {
        return npos;
    }
    for (size_t i = pos; i <= _size - len; ++i) {
        if (str_cmp(s, i, len) == 0) {
            return i;
        }
    }
    return npos;
}

void string::push_back(char c) {
    if (_size == _capacity) {
        reserve(_capacity * 2);
    }
    _str[_size++] = c;
    _str[_size] = '\0';
}

void string::append(const char* str) {
    int new_len = strlen(str) + _size;
    if (new_len > _capacity) {
        reserve(new_len);
    }
    strcpy(_str + _size, str);
    _size = new_len;
}

string& string::operator+=(const char c) { return *this += string(c); }
string& string::operator+=(const char* str) {
    append(str);
    return *this;
}

string& string::operator+=(const string& str) {
    *this += str.c_str();
    _size += str.size();
    return *this;
}

string& string::operator=(const string& s) {
    if (this != &s) {
        delete[] _str;
        _size = s._size;
        _capacity = s._capacity;
        _str = new char[_capacity + 1];
        strcpy(_str, s._str);
    }
    return *this;
}

void string::resize(size_t n, char c) {
    if (n > _size) {
        reserve(n);
        memset(_str + _size, c, n - _size);
    }
    _size = n;
    _str[_size] = '\0';
}

void string::reserve(size_t n) {
    if (n > _capacity) {
        char* new_str = new char[n + 1];
        strcpy(new_str, _str);
        delete[] _str;
        _str = new_str;
        _capacity = n;
    }
}

bool string::operator<(const string& s) { return !(*this >= s); }

bool string::operator<=(const string& s) { return !(*this > s); }

bool string::operator>(const string& s) {
    for (int i = 0; i < _size && i < s._size; ++i) {
        if (_str[i] != s._str[i]) {
            return _str[i] > s._str[i];
        }
    }
    return _size > s._size;
}

bool string::operator>=(const string& s) { return *this > s || *this == s; }

bool string::operator==(const string& s) {
    if (_size != s._size) {
        return false;
    }
    for (size_t i = 0; i < _size; ++i) {
        if (_str[i] != s._str[i]) {
            return false;
        }
    }
    return true;
}

bool string::operator!=(const string& s) { return !(*this == s); }

string& string::insert(size_t pos, char c) {
    if (pos > _size) {
        throw "string::insert: pos > size";
    }

    if (_size + 1 > _capacity) {
        _capacity == 0 ? _capacity = 1 : _capacity *= 2;
        reserve(_capacity);
    }
    for (size_t i = _size; i > pos; --i) {
        _str[i] = _str[i - 1];
    }
    _str[pos] = c;
    ++_size;
    _str[_size] = '\0';
    return *this;
}

string& string::insert(size_t pos, const char* str) {
    if (pos > _size) {
        throw "string::insert: pos > size";
    }
    size_t len = strlen(str);
    cout << len << endl;
    if (len == 0) {
        return *this;
    }
    if (_size + len > _capacity) {
        reserve(std::max(_size + len, _capacity * 2));
    }
    memmove(_str + pos + len, _str + pos, _size - pos);
    memmove(_str + pos, str, len);
    _size += len;
    _str[_size] = '\0';
    return *this;
}

string& string::insert(size_t pos, const string& s) {
    if (pos > _size) {
        throw "string::insert: pos > size";
    }
    if (_size + s._size > _capacity) {
        reserve(_capacity * 2);
    }
    memmove(_str + pos + s._size, _str + pos, _size - pos);
    memmove(_str + pos, s.c_str(), s._size);
    _size += s._size;
    _str[_size] = '\0';
    return *this;
}

string& string::erase(size_t pos, size_t len) {
    if (len == npos || pos + len >= _size) {
        len = _size - pos;
    }
    memmove(_str + pos, _str + pos + len, _size - pos - len);
    _size -= len;
    _str[_size] = '\0';
    return *this;
}

string string::substr(size_t pos, size_t len) {
    if (len == npos || pos + len >= _size) {
        len = _size - pos;
    }
    string sub;
    sub.reserve(len);
    sub.append(_str + pos);
    sub._str[len] = '\0';
    return sub;
}

};  // namespace sympsel
